'''
        OTP to TM
        http://maps5/otp?fromPlace=45.587647,-122.593173&toPlace=45.5097,-122.71629&arr=Depart&min=QUICK&maxWalkDistance=840&mode=TRANSIT,WALK&itinID=1&date=05/27/2011&time=4:34%20pm&submit
        http://maps/maps?fromPlace=45.587647,-122.593173&toPlace=45.5097,-122.71629&arr=Depart&min=QUICK&maxWalkDistance=xxx&date=05/27/2011&time=4:34%20pm&submit
        http://ride/maps?fromPlace=45.587647,-122.593173&toPlace=45.5097,-122.71629&arr=Depart&min=T&walk=0.50&mode=A&itinID=1&date=05/27/2011&time=4:34%20pm&submit
        
'''
import iso8601
import logging
from xml.dom import minidom

from   urldb.model.url import *

from .call_service_base import *
from .parse_service_base import *
from .. import tables


class CallService(CallServiceBase):

    def __init__(self, c, domain, minutes=True):
        super(CallService, self).__init__()

        '''
        '''
        self.control = c
        self.domain = domain
        self.parser = ParseService(minutes)

        self.url_path = '/prod?'
        self.urls = None

    def call_via_atis(self, atis_trip):
        ''' build a url to OTP, using reqest information from a successful call to ATIS.  
            Then call the OTP service, which will eventually land in the parse routine below...
        
            http://maps5.trimet.org/prod?arriveBy=false&time=5:55 PM&mode=TRANSIT,WALK&optimize=QUICK&maxWalkDistance=840&toPlace=45.5097,-122.71629&fromPlace=45.587647,-122.593173
            http://maps5.trimet.org/maps/?Arr=D&time=1:38 pm&Mode=A&Min=T&Walk=0.50&toCoord=45.5097,-122.71629&fromCoord=45.587647,-122.593173
        '''
        param_dict = {}

        # step 1: get atis data that we need to make a call to OTP
        atis_rec = atis_trip.url_record
        atis_params = Url.params_to_dict(atis_rec.params)

        # step 2: convert atis param values to OTP values
        param_dict['fromPlace'] = str(atis_trip.from_lat) + "," + str(atis_trip.from_lon)
        param_dict['toPlace'] = str(atis_trip.to_lat) + "," + str(atis_trip.to_lon)
        param_dict['arriveBy'] = False
        if atis_params.has_key('time'): param_dict['time'] = atis_params['time']
        if atis_params.has_key('Arr') and "A" in atis_params['Arr']: param_dict['arriveBy'] = True
        if atis_params.has_key('Walk'): param_dict['maxWalkDistance'] = float(atis_params['Walk']) * 1680
        if atis_params.has_key('Min'):
            if atis_params['Min'] == 'T':  param_dict['optimize'] = 'QUICK'
            if atis_params['Min'] == 'F':  param_dict['optimize'] = 'FAST'
        if atis_params.has_key('Mode'):
            if atis_params['Mode'] == 'A':  param_dict['mode'] = "TRANSIT,WALK"
            if atis_params['Mode'] == 'T':  param_dict['mode'] = "TRAINISH,WALK"
            if atis_params['Mode'] == 'B':  param_dict['mode'] = "BUSISH,WALK"

        path = self.domain + self.url_path
        params = urllib.urlencode(param_dict)
        url = path + params
        logging.info("otp url via atis:" + url)
        trip = self.call_url(url, atis_rec)
        if trip != None:
            trip.otp_params = param_dict
            trip.params = params
        return trip


class ParseService(ParseServiceBase):
    '''
    '''

    def __init__(self, minutes):
        super(ParseService, self).__init__()
        self.minutes = minutes

    def parse(self, doc, url, url_rec):
        trip = super(ParseService, self).parse(doc, url, url_rec)

        # step 1: parse the xml document
        trip.trip_planner = 'OTP'
        dom = minidom.parseString(doc)

        # step 2: find high-level elements in dom
        dom_from = dom.getElementsByTagName('from')[0]
        dom_to = dom.getElementsByTagName('to')[0]
        dom_request = dom.getElementsByTagName('requestParameters')[0]
        dom_itineraries = dom.getElementsByTagName('itinerary')

        # step 3: parse from & to parameters (set to self, for call to self.makeItinerary() below)
        trip.from_lat, trip.from_lon = ParseService.xml_coord(dom_from)
        trip.from_name = ParseService.xml_value(dom_from, 'name')
        trip.to_lat, trip.to_lon = ParseService.xml_coord(dom_to)
        trip.to_name = ParseService.xml_value(dom_to, 'name')

        #step 4: parse out the trip options
        #self.arrive_flag = ParseService.xml_key_value(dom_request, 'time')
        trip.optimize_flag = ParseService.xml_key_value(dom_request, 'optimize')
        trip.arrive_flag = ParseService.xml_key_value(dom_request, 'arriveBy')
        trip.walk_distance = ParseService.xml_key_value(dom_request, 'maxWalkDistance')
        trip.mode = ParseService.xml_key_value(dom_request, 'mode')

        d = ParseService.xml_key_value(dom_request, 'date')
        t = ParseService.xml_key_value(dom_request, 'time')
        trip.date_time = ParseService.make_datetime(d, t)

        # step 5: parse out the data for the the itinerary object(s)
        self.parse_itineraries(trip, dom_itineraries)
        trip.message = ParseService.xml_value(dom, 'message')
        self.trips.append(trip)
        return trip

    def parse_itinerary(self, trip, td):
        '''
          <startTime>2011-06-08T11:43:51-07:00</startTime>
          <enself.time_key_valueime>2011-06-08T12:37:17-07:00</endTime>
          <duration>3206000</duration>
          <walkTime>1178000</walkTime>
          <transitTime>1680000</transitTime>
          <waitingTime>348000</waitingTime>
          <transfers>1</transfers>

          <walkDistance>1564.7104729742737</walkDistance>

          <elevationLost>186.20101696980163</elevationLost>
          <elevationGained>13.05196999478973</elevationGained>
          <tooSloped>false</tooSloped></itinerary>
          <fare><fare><entry><key>regular</key><value><cents>205</cents><currency/></value></entry></fare></fare>
        '''

        itin = self.make_itinerary(trip)
        itin.walk_time = self.time_key_value(td, 'walkTime')
        itin.transit_time = self.time_key_value(td, 'transitTime')
        itin.wait_time = self.time_key_value(td, 'waitingTime')
        itin.duration = self.time_key_value(td, 'duration')
        itin.transfers = ParseService.xml_value(td, 'transfers')

        st = ParseService.xml_value(td, 'startTime')
        et = ParseService.xml_value(td, 'endTime')
        itin.start_time = iso8601.parse_date(st)
        itin.end_time = iso8601.parse_date(st)
        # itin.distance = ADD UP LEG DISTNACES 

        return itin



    def time_key_value(self, dom, key):
        val = ParseService.xml_value(dom, key)
        if self.minutes:
            val = int(val) / (1000 * 60)
        return val
